#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <algorithm>
#include <random>
#include <string>
#include<iostream>

// g++ -shared -O3 preprocess.cpp -ldl -mavx -o preprocess.so -fPIC
static void fill_mat_0(float*, int*, char*);
static void fill_mat_1(float*, int*, char*);
static void fill_mat_2(float*, int*, char*);
static void fill_mat_3(float*, int*, char*);
const int mat_size = 34 * 4;
const int layer_num = 59;
const int three_axis_mat_size = layer_num * mat_size;

static int batch_size;
static int epoch_len; 
static size_t index_size;
static size_t *index_buf;
static char *csv_buf;
static int data_arg;
static int data_arg_on;
static int task;

void (*fill_mats[4])(float*, int*, char*) = {fill_mat_0, fill_mat_1, fill_mat_2, fill_mat_3};
static const int char2int[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
static const int hashmap[128] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -49, 0, 0, -40, 0, 0, -31, 0, 0, 0, 0, 0, 0, -22, 0, 0, 0, 0, 0};

static void string2mat(float *mat, char *&str)
{
    static int index_map[12][128] = {
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 72, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 72, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 36, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 36, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 28, 24, 20, 16, 12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0},
    };

    int base; // 该花色的基数
    int book[9]; // 记录该花色下各牌的数量

    while(*str != ',') // 遍历字符串
    {
        if(*str < ':') // 数字
        {
            int num = *str - '1';
            int index = base + num * 4 + book[num]++;
            mat[index] = 1;
        }
        else // 表示花色的字母
        {
            base = index_map[data_arg][*str];
            memset(book, 0, sizeof(book));
        }
        str++;
    }

    str++; // 跳过逗号
}

static inline void mat_zeros(float *mat)
{
    memset(mat, 0, mat_size);
}

static inline void mat_ones(float *mat)
{
    std::fill(mat, mat + mat_size, float(1.0));
}

static void bool2mat(float *mat, char *&str)
{
    if(*str == ',') // bool == 0
    {
        str++;
        // mat_zeros(mat); 本来就是全部置0的
    }
    else
    {
        str += 2;
        mat_ones(mat);
    }
}

static void aka2mat(float *mat, char *&str)
{
    if(*str == ',')
    {
        str++;
        return;
    }

    static int base[3] = {4 * 4, 13 * 4, 22 * 4};

    int num = char2int[*str];
    // mat_zeros(mat); 开始时就全部置空了

    for(int i = 0, j = 4; i < 3; i++, j >>= 1)
        if(num & j)
        {
            float *ptr = &mat[base[i]];
            std::fill(ptr, ptr + 4, float(1.0));
        }
    
    str += 2; // 跳过该字符和逗号
}

static inline int string2tilenum(char *&str)
{
    int tilenum = hashmap[str[0]] + str[1]; // lsy造hash算法。将'm'转换成-'1'，'p'转换成-'1' + 9，以此类推
    str += 2;
    return tilenum;
}

static inline void wind2mat(float *mat, int num)
{
    const int base = 108; // 字母z的起始索引
    int index = base + num;

    float *ptr = &mat[index];
    std::fill(ptr, ptr + 4, float(1.0));
}

static inline int lsy_atoi(char *&ptr) // 0~99的特化版本，会顺便带着ptr走到逗号的下一个位置
{
    int val = *ptr++ - '0';
    if(*ptr != ',')
        val = (*ptr++ - '0') + (val << 1) + (val << 3);
    ptr++;
    return val;
}

static void self2mat(float *mat, char *&str) // 这个函数会写三个矩阵
{
    // (df[i][39] + df[i][0]) % 4 self_wind
    // 场风
    int self_num = char2int[*str]; // 玩家编号
    str += 2;

    int round = lsy_atoi(str); // 小局数，有可能超过10，所以要用atoi
    wind2mat(mat, round / 4);

    // 自风
    int self_wind = (self_num + round) % 4;
    wind2mat(mat + mat_size, self_wind);

    // 小局数。
    static int round_map[16] = {mat_size * (2 + 0), mat_size * (2 + 1), mat_size * (2 + 2), mat_size * (2 + 3), mat_size * (2 + 4), mat_size * (2 + 5), mat_size * (2 + 6), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7), mat_size * (2 + 7)};
    mat_ones(mat + round_map[round]);
}

static void rank2mat(float *mat, char *&str)
{
    int my_rank = char2int[*str]; // 自家顺位
    mat_ones(mat + mat_size * my_rank);
    
    str += 2;
}

static void hand_discard2mat(float *mat, char *&str)
{
    for(int i = 0; i < 3; i++)
    {
        // 最近 i + 1 次手切
        string2mat(mat, str);
        // 最近 i + 1 次手切红5
        aka2mat(mat + mat_size, str);
    }
}

static inline void skip_row(char *&str) // 跳过暂不需要的列
{
    while(*str++ != ',');
}

static void fill_mat_0(float *X, int *y, char *str)
{
    // 场风、自风
    self2mat(X, str);

    // 自家顺位
    rank2mat(X + 10 * mat_size, str);

    // 自家手牌
    string2mat(X + 14 * mat_size, str);
    // 自家手牌红5
    aka2mat(X + 15 * mat_size, str);

    // 自家舍牌
    string2mat(X + 16 * mat_size, str);
    // 跳过自家舍牌红5
    skip_row(str);

    // 下家早巡舍牌
    string2mat(X + 17 * mat_size, str);
    // 下家中巡舍牌
    string2mat(X + 18 * mat_size, str);
    // 下家晚巡舍牌
    string2mat(X + 19 * mat_size, str);
    // 下家立直前舍牌
    string2mat(X + 20 * mat_size, str);
    // 下家立直宣言牌
    string2mat(X + 21 * mat_size, str);
    // 下家立直后舍牌
    string2mat(X + 22 * mat_size, str);
    // 下家舍牌红5
    aka2mat(X + 23 * mat_size, str);

    // 对家早巡舍牌
    string2mat(X + 24 * mat_size, str);
    // 对家中巡舍牌
    string2mat(X + 25 * mat_size, str);
    // 对家晚巡舍牌
    string2mat(X + 26 * mat_size, str);
    // 对家立直前舍牌
    string2mat(X + 27 * mat_size, str);
    // 对家立直宣言牌
    string2mat(X + 28 * mat_size, str);
    // 对家立直后舍牌
    string2mat(X + 29 * mat_size, str);
    // 对家舍牌红5
    aka2mat(X + 30 * mat_size, str);

    // 上家早巡舍牌
    string2mat(X + 31 * mat_size, str);
    // 上家中巡舍牌
    string2mat(X + 32 * mat_size, str);
    // 上家晚巡舍牌
    string2mat(X + 33 * mat_size, str);
    // 上家立直前舍牌
    string2mat(X + 34 * mat_size, str);
    // 上家立直宣言牌
    string2mat(X + 35 * mat_size, str);
    // 上家立直后舍牌
    string2mat(X + 36 * mat_size, str);
    // 上家舍牌红5
    aka2mat(X + 37 * mat_size, str);

    // 自家副露
    string2mat(X + 38 * mat_size, str);
    // 自家副露红5
    aka2mat(X + 39 * mat_size, str);
    // 下家副露
    string2mat(X + 40 * mat_size, str);
    // 下家副露红5
    aka2mat(X + 41 * mat_size, str);
    // 对家副露
    string2mat(X + 42 * mat_size, str);
    // 对家副露红5
    aka2mat(X + 43 * mat_size, str);
    // 上家副露
    string2mat(X + 44 * mat_size, str);
    // 上家副露红5
    aka2mat(X + 45 * mat_size, str);

    // 宝牌指示牌
    string2mat(X + 46 * mat_size, str);
    // 下家立直
    bool2mat(X + 47 * mat_size, str);
    // 对家立直
    bool2mat(X + 48 * mat_size, str);
    // 上家立直
    bool2mat(X + 49 * mat_size, str);
    // 下家立直一发
    bool2mat(X + 50 * mat_size, str);
    // 对家立直一发
    bool2mat(X + 51 * mat_size, str);
    // 上家立直一发
    bool2mat(X + 52 * mat_size, str);
    
    // mode0
    // 下家最近一次手切	下家最近一次手切红5	下家最近二次手切	下家最近二次手切红5	下家最近三次手切	下家最近三次手切红5
    hand_discard2mat(X + 53 * mat_size, str);
    // 对家最近一次手切	对家最近一次手切红5	对家最近二次手切	对家最近二次手切红5	对家最近三次手切	对家最近三次手切红5
    hand_discard2mat(X + 55 * mat_size, str);
    // 上家最近一次手切	上家最近一次手切红5	上家最近二次手切	上家最近二次手切红5	上家最近三次手切	上家最近三次手切红5
    hand_discard2mat(X + 57 * mat_size, str);

    // 操作的牌
    *y = string2tilenum(str);
}

static void fill_mat_1(float *X, int *y, char *str)
{
    // 场风、自风
    self2mat(X, str);

    // 自家顺位
    rank2mat(X + 10 * mat_size, str);

    // 自家手牌
    string2mat(X + 14 * mat_size, str);
    // 自家手牌红5
    aka2mat(X + 15 * mat_size, str);

    // 自家舍牌
    string2mat(X + 16 * mat_size, str);
    // 跳过自家舍牌红5
    skip_row(str);

    // 下家早巡舍牌
    string2mat(X + 17 * mat_size, str);
    // 下家中巡舍牌
    string2mat(X + 18 * mat_size, str);
    // 下家晚巡舍牌
    string2mat(X + 19 * mat_size, str);
    // 下家立直前舍牌
    string2mat(X + 20 * mat_size, str);
    // 下家立直宣言牌
    string2mat(X + 21 * mat_size, str);
    // 下家立直后舍牌
    string2mat(X + 22 * mat_size, str);
    // 下家舍牌红5
    aka2mat(X + 23 * mat_size, str);

    // 对家早巡舍牌
    string2mat(X + 24 * mat_size, str);
    // 对家中巡舍牌
    string2mat(X + 25 * mat_size, str);
    // 对家晚巡舍牌
    string2mat(X + 26 * mat_size, str);
    // 对家立直前舍牌
    string2mat(X + 27 * mat_size, str);
    // 对家立直宣言牌
    string2mat(X + 28 * mat_size, str);
    // 对家立直后舍牌
    string2mat(X + 29 * mat_size, str);
    // 对家舍牌红5
    aka2mat(X + 30 * mat_size, str);

    // 上家早巡舍牌
    string2mat(X + 31 * mat_size, str);
    // 上家中巡舍牌
    string2mat(X + 32 * mat_size, str);
    // 上家晚巡舍牌
    string2mat(X + 33 * mat_size, str);
    // 上家立直前舍牌
    string2mat(X + 34 * mat_size, str);
    // 上家立直宣言牌
    string2mat(X + 35 * mat_size, str);
    // 上家立直后舍牌
    string2mat(X + 36 * mat_size, str);
    // 上家舍牌红5
    aka2mat(X + 37 * mat_size, str);

    // 自家副露
    string2mat(X + 38 * mat_size, str);
    // 自家副露红5
    aka2mat(X + 39 * mat_size, str);
    // 下家副露
    string2mat(X + 40 * mat_size, str);
    // 下家副露红5
    aka2mat(X + 41 * mat_size, str);
    // 对家副露
    string2mat(X + 42 * mat_size, str);
    // 对家副露红5
    aka2mat(X + 43 * mat_size, str);
    // 上家副露
    string2mat(X + 44 * mat_size, str);
    // 上家副露红5
    aka2mat(X + 45 * mat_size, str);

    // 宝牌指示牌
    string2mat(X + 46 * mat_size, str);
    // 下家立直
    bool2mat(X + 47 * mat_size, str);
    // 对家立直
    bool2mat(X + 48 * mat_size, str);
    // 上家立直
    bool2mat(X + 49 * mat_size, str);
    // 下家立直一发
    bool2mat(X + 50 * mat_size, str);
    // 对家立直一发
    bool2mat(X + 51 * mat_size, str);
    // 上家立直一发
    bool2mat(X + 52 * mat_size, str);
    
    // mode0
    // 下家最近一次手切	下家最近一次手切红5	下家最近二次手切	下家最近二次手切红5	下家最近三次手切	下家最近三次手切红5
    hand_discard2mat(X + 53 * mat_size, str);
    // 对家最近一次手切	对家最近一次手切红5	对家最近二次手切	对家最近二次手切红5	对家最近三次手切	对家最近三次手切红5
    hand_discard2mat(X + 55 * mat_size, str);
    // 上家最近一次手切	上家最近一次手切红5	上家最近二次手切	上家最近二次手切红5	上家最近三次手切	上家最近三次手切红5
    hand_discard2mat(X + 57 * mat_size, str);


    // 可吃的牌
    *y = string2tilenum(str);
}

static void fill_mat_2(float* x, int* y, char* str){
}

static void fill_mat_3(float* x, int* y, char* str){
}
static void read_in(const char *index_file_name, const char *csv_file_name)
{
    std::ifstream fin;
    fin.open(index_file_name, std::ios::binary);
    if(!fin)
    {
        std::cout << "File: " << index_file_name << "does not exist!" << std::endl;
        exit(1);
    }

	fin.seekg(0, std::ios::end); //设置文件指针到文件流的尾部
	size_t index_file_size = fin.tellg(); //读取文件指针的位置，单位为“字节”
    fin.seekg(0, std::ios::beg); //设置文件指针到文件流的开始

    index_size = index_file_size / sizeof(size_t); // 索引数组长度
    index_buf = new size_t[index_size];

    fin.read(reinterpret_cast<char *>(index_buf), index_file_size);
    fin.close();

    fin.open(csv_file_name, std::ios::binary);
    if(!fin)
    {
        std::cout << "File: " << csv_file_name << "does not exist!" << std::endl;
        exit(1);
    }
	fin.seekg(0, std::ios::end); //设置文件指针到文件流的尾部
	size_t csv_size = fin.tellg(); //读取文件指针的位置，单位为“字节”
    fin.seekg(0, std::ios::beg); //设置文件指针到文件流的开始

    csv_buf = new char[csv_size];
    fin.read(csv_buf, csv_size);
}

extern "C" void shuffle_index()
{
    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(index_buf, index_buf + index_size, g);
}

extern "C" void get_item(float *X, int *y, int index)
{
    if(data_arg_on){
        std::random_device rd;
        std::mt19937 g(rd());
        std::uniform_int_distribution<> dis(0, 11);
        for(int i = 0; i < batch_size; i++){
            data_arg = dis(g);
            fill_mats[task](X + three_axis_mat_size * i, y + i, csv_buf + index_buf[index + i]);
        }
    }
    else{
        data_arg = 0;
        for(int i = 0; i < batch_size; i++)
            fill_mats[task](X + three_axis_mat_size * i, y + i, csv_buf + index_buf[index + i]);
    }
    
/*     for(int end = index + batch_size; index < end; index++, X += three_axis_mat_size, y++)
        fill_mat(X, y, csv_buf + index_buf[index]); */
}

extern "C" void init(const wchar_t *index_file_name, const wchar_t *csv_file_name, int init_batch_size, int gen_task, int gen_dataarg_on)
{
    const size_t max_file_name = 32;

    char str1[max_file_name], str2[max_file_name];
    wcstombs(str1, index_file_name, max_file_name);
    wcstombs(str2, csv_file_name, max_file_name);

    read_in(str1, str2);

    batch_size = init_batch_size;
    std::cout << "size:" << std::endl << index_size << " " << init_batch_size << std::endl;
    epoch_len = index_size / init_batch_size;
    data_arg_on = gen_dataarg_on;
    std::cout << "data_arg_on:" << data_arg_on << std::endl;
    task = gen_task;
    shuffle_index();
}

extern "C" size_t get_len()
{
    return epoch_len;
}